package com.songlanyun.modules.servicegoods.service.impl;

import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.BeanUtil;
import com.songlanyun.common.validator.ValidatorUtils;
import com.songlanyun.common.validator.group.UpdateGroup;
import com.songlanyun.modules.exception.GoodsExceptionEnum;
import com.songlanyun.modules.exception.ServiceGoodsExceptionEnum;
import com.songlanyun.modules.group.entity.ProductGoodsGroupEntity;
import com.songlanyun.modules.group.model.vo.GoodsGroupSlim;
import com.songlanyun.modules.servicegoods.entity.ServiceGoodsClassify;
import com.songlanyun.modules.servicegoods.model.dto.ServiceGoodsGroupDTO;
import com.songlanyun.modules.shop.service.ShopService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.utils.PageUtils;
import com.songlanyun.common.utils.Query;

import com.songlanyun.modules.servicegoods.dao.ServiceGoodsGroupDao;
import com.songlanyun.modules.servicegoods.entity.ServiceGoodsGroup;
import com.songlanyun.modules.servicegoods.service.ServiceGoodsGroupService;
import org.springframework.transaction.annotation.Transactional;


@Service("serviceGoodsGroupService")
public class ServiceGoodsGroupServiceImpl extends ServiceImpl<ServiceGoodsGroupDao, ServiceGoodsGroup> implements ServiceGoodsGroupService {

    @Autowired
    private ShopService shopService;


    @Override
    public ServiceGoodsGroup create(ServiceGoodsGroup entity) {
        ValidatorUtils.validateEntity(entity);
        validateNameExists(entity);
        validateParent(entity);
        this.baseMapper.insert(entity);
        return entity;
    }

    private void validateNameExists(ServiceGoodsGroup entity) {
        ServiceGoodsGroup target = this.getOne(new LambdaQueryWrapper<ServiceGoodsGroup>()
                .eq(ServiceGoodsGroup::getName, entity.getName())
                .eq(ServiceGoodsGroup::getShopId, entity.getShopId())
                .last("limit 1"));
        if (target != null && !target.equals(entity)) {
            throw new RRException(ServiceGoodsExceptionEnum.SERVICE_GROUP_NAME_REPEAT);
        }
    }

    private void validateParent(ServiceGoodsGroup entity)
    {
        if(entity.getParentId()==0L) return ;
        ServiceGoodsGroup parent = this.getByShopIdAndId(entity.getShopId(),entity.getParentId());
        if (parent == null) {
            throw new RRException(ServiceGoodsExceptionEnum.SERVICE_GROUP_PARENT_NOT_EXISTS);
        }

        if (parent.getParentId() > 0) {
            throw new RRException(ServiceGoodsExceptionEnum.SERVICE_GROUP_SECOND_SAFE);
        }
    }
    @Override
    public ServiceGoodsGroup getByShopIdAndId(Long shopId,Long id)
    {
        ServiceGoodsGroup target = this.getOne(new LambdaQueryWrapper<ServiceGoodsGroup>()
                .eq(ServiceGoodsGroup::getId, id)
                .eq(ServiceGoodsGroup::getShopId, shopId)
                .last("limit 1"));
        return target;
    }

    @Override
    public ServiceGoodsGroup modify(ServiceGoodsGroup entity) {
        ValidatorUtils.validateEntity(entity);
        validateNameExists(entity);
        validateUpdateParentSafe(entity);
        this.baseMapper.updateById(entity);
        return entity;
    }

    private void validateUpdateParentSafe(ServiceGoodsGroup entity) {
        if(entity.getParentId()>0)
        {
            //如果自己还有下级，说明现在成了三级，但是系统只需要两级，所以要报错

            ServiceGoodsGroup parent = this.getByShopIdAndId(entity.getShopId(),entity.getParentId());
            if(parent==null)
            {
                throw new RRException(ServiceGoodsExceptionEnum.SERVICE_GROUP_PARENT_NOT_EXISTS);
            }

            if(parent.getParentId()>0)
            {
                throw new RRException(ServiceGoodsExceptionEnum.SERVICE_GROUP_SECOND_SAFE);
            }

            if(entity.getParentId().equals(entity.getId()))
            {
                throw new RRException(ServiceGoodsExceptionEnum.SERVICE_GROUP_SELECT_SELF);
            }

            if(entity.loadChildren().size()>0)
            {
                throw new RRException(ServiceGoodsExceptionEnum.SERVICE_GROUP_SECOND_SAFE);
            }


        }
    }


    @Override
    public void remove(Long id) {
        validateRemoveSafe(id);
        this.removeById(id);
    }


    /**
     * 服务商家创建商品分组
     * @param shopId
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public ServiceGoodsGroup add(Long shopId, ServiceGoodsGroupDTO dto) {

        shopService.loadShopBy(shopId,true);
        ServiceGoodsGroup entity = new ServiceGoodsGroup();
        BeanUtil.copyPropertiesIgnoreNull(dto,entity);
        entity.setShopId(shopId);
        return this.create(entity);
    }

    /**
     * 服务商家修改商品分组
     * @param shopId
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public ServiceGoodsGroup update(Long shopId, ServiceGoodsGroupDTO dto) {
        shopService.loadShopBy(shopId,true);
        ServiceGoodsGroup load = this.getById(dto.getId(),true);
        if(load!=null&& !load.getShopId().equals(shopId))
        {
            throw new RRException(ServiceGoodsExceptionEnum.SERVICE_GROUP_SHOP_SAFE);
        }

        BeanUtil.copyPropertiesIgnoreNull(dto,load);
        return this.modify(load);
    }

    @Override
    public List<ServiceGoodsGroup> getChildren( Long id) {
        List<ServiceGoodsGroup> list = this.list(new LambdaQueryWrapper<ServiceGoodsGroup>()
                .eq(ServiceGoodsGroup::getParentId, id));
        return list;
    }

    @Override
    public List<Map<String, Object>> getAllGoodsGroup(Long shopId) {

        List<ServiceGoodsGroup> list = this.list(new LambdaQueryWrapper<ServiceGoodsGroup>()
        .eq(ServiceGoodsGroup::getShopId,shopId));

        List<Map<String, Object>> data =  makeGoodsGroupTree(list, 0L);
        return data;
    }

    @Override
    public void deleteByShopIdAndId(Long shopId, Long id) {
        shopService.loadShopBy(shopId,true);
        ServiceGoodsGroup obj = this.getByShopIdAndId(shopId, id);

        if(obj!=null&& !obj.getShopId().equals(shopId))
        {
            throw new RRException(ServiceGoodsExceptionEnum.SERVICE_GROUP_SHOP_SAFE);
        }
        this.remove(id);
    }

    /**
     * 删除分组时的安全验证
     * 要删除的分组不存在不能删除
     * 下面还有子分组的不能删除
     * @param id
     */
    private void validateRemoveSafe(Long id) {
        ServiceGoodsGroup entity = this.getById(id);
        if (entity == null) {
            throw new RRException(ServiceGoodsExceptionEnum.SERVICE_GROUP_NOT_EXISTS);
        }

        if(entity.loadChildren().size()>0)
        {
            throw new RRException(ServiceGoodsExceptionEnum.SERVICE_GROUP_REMOVE_SAFE);
        }
    }




    @Override
    public List<ServiceGoodsGroup> getFirstProductGoods(Long shopId) {
        List<ServiceGoodsGroup> list = this.list(new LambdaQueryWrapper<ServiceGoodsGroup>()
                .eq(ServiceGoodsGroup::getShopId, shopId)
                .eq(ServiceGoodsGroup::getParentId, 0L));
        return list;
    }

    private List<Map<String, Object>> makeGoodsGroupTree(List<ServiceGoodsGroup> groups, Long parentId) {
        List<Map<String, Object>> list = new ArrayList<>();

        for (ServiceGoodsGroup group : groups) {
            if (group.getParentId().equals(parentId)) {
                Map<String, Object> map = new LinkedHashMap<>();
                map.put("id", group.getId());
                map.put("name", group.getName());
                map.put("parent_id", group.getParentId());
                map.put("order_index", group.getOrderIndex());
                map.put("shop_id", group.getShopId());
                map.put("cover_image", group.getCoverImage());
                map.put("children", makeGoodsGroupTree(groups, group.getId()));
                list.add(map);
            }
        }

        list.sort(new Comparator<Map<String, Object>>() {
            @Override
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                if ((int) o1.get("order_index") <= (int) o2.get("order_index")) {
                    return 1;
                } else {
                    return -1;
                }
            }
        });

        return list;
    }


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String name = MapUtil.getStr(params, "name");
        IPage<ServiceGoodsGroup> page = this.page(
                new Query<ServiceGoodsGroup>().getPage(params),
                new LambdaQueryWrapper<ServiceGoodsGroup>()
                        .like(StringUtils.isNotBlank(name), ServiceGoodsGroup::getName, name)
                        .orderByDesc(ServiceGoodsGroup::getCreateTime)
        );

        return new PageUtils(page);
    }

    @Override
    public ServiceGoodsGroup getById(Long id, boolean isThrow) {

        ServiceGoodsGroup group = this.baseMapper.selectById(id);
        if (group == null) {
            if (isThrow) {
                throw new RRException("服务商品分组不存在");
            }
        }
        return group;

    }

    @Override
    public List<GoodsGroupSlim> selectGoodsGroupRelation(Long id) {
        return this.baseMapper.selectGoodsGroupRelation(id);
    }

}